/*-----------------------------------------------------------------------------
 * stock_server_database.h - Header for core stock server database routines and
 *                           data structures
 *
 * March 2010, Forhad Ahmed
 *-----------------------------------------------------------------------------
 */

#ifndef _STOCK_DATABASE_
#define _STOCK_DATABASE_

#include <pthread.h>
#include "avl_tree.h"
#include "common/include/stock_common.h"
#include "common/include/stock_update.h"


/*
 * Max number of intraday updates expected for a stock.  We assume one update
 * per second. However if there are multiple clients sreaming data for the same
 * stock (client stock lists aren't mutually exclusive) then we can potentially 
 * have more than one update per second. For such cases, we combine all updates 
 * that fall into a 2 second range.
 * 
 * Market is open 7.5 hrs x 3600 secs/hr / 2 secs/updates = 13500 updates
 */
#define STOCK_MAX_UPDATES 13500


#define STOCK_MAX_TEMP 64

typedef struct stock_t stock_t;

/*
 * Data structure that mainly holds information about the intraday values for a
 * stock. It also contains other misc. information to aid in various types of 
 * processing.
 *
 * These blocks are arranged in an AVL tree indexed by the stock ticker name
 */
struct stock_t {
    avl_node   avl;
    stock_t *  next;

    /*
     *
     */
    char       ticker[STOCK_TICKER_LEN];
    uint32_t   current_timestamp;
    int        data_count;
    stock_data data[STOCK_MAX_UPDATES];

    /*
     *
     */
    int        temp_bin_count;
    uint32_t   temp_bin_min_price;
    uint32_t   temp_bin_max_price;
    uint32_t   temp_bin_sum_price;
    stock_data temp_bin[STOCK_MAX_TEMP];

    /*
     * Stats
     */
    uint32_t dropped_unsynchronized;
    uint32_t temp_bin_overflow;

    /*
     * 
     */
    uint32_t temp_updates;
    uint32_t update_rate;
};


/*
 * The stock database structures:
 *   - stock_database: avl tree of stock entries keyed by stock ticker
 *   - stock_database_list: list of stock entries sorted by insersion order
 *   - tree and list mutexes
 *
 * As of now, the database is cumulative only, meaning we only add stuff to
 * the tree/list.  We don't take things out.
 *
 * Semantics of thread safety for these data structures is as follows:
 *
 * - Only one thread can search/insert in the AVL tree
 *     We don't serialize the search and insert operations in the tree
 *
 * - Multiple threads can traverse the database list 
 *     Thread safety is only a concern for the list at the list head since 
 *     we add new nodes only to the beginning of the list. For now, we don't 
 *     have to worry about deleting nodes from the middle of the list
 */
extern avl_tree        *stock_database;
extern stock_t         *stock_database_list;
extern pthread_mutex_t  stock_database_mutex;
extern pthread_mutex_t  stock_database_list_mutex;


/*
 * 
 */
#define FOR_ALL_STOCKS(s)           \
    STOCK_DATABASE_LIST_LOCK();     \
    s = stock_database_list;        \
    STOCK_DATABASE_LIST_UNLOCK();   \
    for ( ; s != NULL; s = s->next) 


/*
 *
 */
#define STOCK_DATABASE_LIST_LOCK() \
    pthread_mutex_lock(&stock_database_list_mutex)

#define STOCK_DATABASE_LIST_UNLOCK() \
    pthread_mutex_unlock(&stock_database_list_mutex)


int
stock_database_init();


int
stock_database_cleanup();


stock_t *
stock_search(char *ticker, int insensitive);


uint32_t 
stock_last_price(stock_t *stock);


uint32_t
stock_last_timestamp(stock_t *stock);


stock_update *
stock_database_insert(stock_update *update);



#define STOCK_DATABASE_FILTER_UNSYNC 0xFF

int
stock_database_filter(stock_update *update);

#endif /* _STOCK_DATABASE_ */

